package models

import (
	"gitchina/kly_service/data"
	"gitchina/kly_service/errors"
	"gitchina/kly_service/util"
	"strconv"
	"time"
)

type CarrierPubRQ struct {
	StartArea    string  `json:"start_area"`
	EndArea      string  `json:"end_area"`
	ShipmentTime string  `json:"shipment_time"`
	Load         int     `json:"load"`
	Price        float32 `json:"price"`
}

type CarrierPubRS struct {
	Id           ID      `json:"carrier_pub_id"`
	StartArea    string  `json:"start_area"`
	EndArea      string  `json:"end_area"`
	ShipmentTime string  `json:"shipment_time"`
	Load         int     `json:"vehicle_load"`
	State        int     `json:"state"`
	Price        float32 `json:"price"`
}

type GetCarrierPubRQ struct {
	Id ID `json:"carrier_pub_id"`
}

type QueryCarrierPubListRQ struct {
	StartArea   string `json:"start_area"`
	EndArea     string `json:"end_area"`
	TimeBegin   string `json:"time_begin"`
	TimeEnd     string `json:"time_end"`
	VehicleType string `json:"vehicle_type"`
	VehicleLen  string `json:"vehicle_len"`
	VehicleLoad string `json:"vehicle_load"`
	PageNo      int    `json:"page_no"`
	PageSize    int    `json:"page_size"`
}

type CarrierPubListRS struct {
	TotalCount int              `json:"total_count"`
	List       []CarrierPubList `json:"pub_list"`
}

type CarrierPubList struct {
	OwnerName       string  `json:"owner_name"`
	OwnerStars      int     `json:"owner_stars"`
	OwnerPhone      string  `json:"owner_phone"`
	OwnerId         ID      `json:"owner_id"`
	CarrierPubId    ID      `json:"carrier_pub_id"`
	StartArea       string  `json:"start_area"`
	EndArea         string  `json:"end_area"`
	VehicleType     string  `json:"vehicle_type"`
	VehicleLen      string  `json:"vehicle_len"`
	VehicleLoad     string  `json:"vehicle_load"`
	VehiclePhotoUrl string  `json:"vehicle_photo"`
	ShipmentTime    string  `json:"shipment_time"`
	Price           float32 `json:"price"`
}

type CarrierPubDetailRS struct {
	Name           string  `json:"name"`
	OwnerPhone     string  `json:"phone"`
	OwnerStars     int     `json:"stars"`
	CarrierPubId   string  `json:"carrier_pub_id"`
	MemberId       string  `json:"owner_id"`
	StartArea      string  `json:"start_area"`
	EndArea        string  `json:"end_area"`
	Price          float32 `json:"price"`
	ShipmentTime   string  `json:"shipment_time"`
	VehicleType    string  `json:"vehicle_type"`
	VehicleLen     string  `json:"vehicle_len"`
	VehicleLoad    string  `json:"vehicle_load"`
	VehicleNo      string  `json:"vehicle_no"`
	CargoType      string  `json:"cargo_type"`
	MemberPhotoUrl string  `json:"owner_photo_url"`
}

func (l Logistics) CarrierPub(mbrId ID, rq *CarrierPubRQ) (pubId ID, err error) {
	var id int64
	var authState string
	var srcCounty, srcCity, srcProvince, destCounty, destCity, destProvince int
	var shipmentTime time.Time
	var repo data.LogisticsRepo
	var mbrRepo data.MemberRepo

	if srcCounty, err = strconv.Atoi(rq.StartArea); err != nil || srcCounty == 0 {
		err = errors.New(errors.MSG_Logi_Invalid_Start_Area)
		return
	}

	if destCounty, err = strconv.Atoi(rq.EndArea); err != nil || destCounty == 0 {
		err = errors.New(errors.MSG_Logi_Invalid_End_Area)
		return
	}

	if rq.ShipmentTime == "" {
		rq.ShipmentTime = "2100-01-01 00:00:00"
	}

	if shipmentTime, err = time.Parse("2006-01-02 15:04:05", rq.ShipmentTime); err != nil {
		err = errors.New(errors.MSG_Logi_Invalid_Shipment_Time)
		return
	}

	if time.Now().Sub(shipmentTime) >= 0 {
		err = errors.New(errors.MSG_Logi_Invalid_Shipment_Time)
		return
	}

	if _, _, _, id, err = mbrId.Decode(); err != nil {
		err = errors.New(errors.MSG_Mbr_Invalid)
		return
	}

	if srcCounty%10000 == 0 {
		srcProvince = srcCounty
		srcCity = 0
		srcCounty = 0
	} else if srcCounty%100 == 0 {
		srcProvince = srcCounty - srcCounty%10000
		srcCity = srcCounty
		srcCounty = 0
	} else {
		srcProvince = srcCounty - srcCounty%10000
		srcCity = srcCounty - srcCounty%100
	}

	if destCounty%10000 == 0 {
		destProvince = destCounty
		destCity = 0
		destCounty = 0
	} else if destCounty%100 == 0 {
		destProvince = destCounty - destCounty%10000
		destCity = destCounty
		destCounty = 0
	} else {
		destProvince = destCounty - destCounty%10000
		destCity = destCounty - destCounty%100
	}

	authState, err = mbrRepo.GetEntiAuthState(int(id), data.Mbr_carrier_owner_type)
	if err != nil {
		util.GetLogger().Error("[model-LinePub] - error:%s", err.Error())
		err = errors.New(errors.MSG_Logi_Line_Pub_Add_Error)
		return
	}

	if authState != "2" {
		err = errors.New(errors.MSG_Mbr_Upd_Info_Not_Allowed)
		return
	}

	id, err = repo.AddCarrierPub(&data.CarrierPubDto{
		MemberId:     int(id),
		SrcProvince:  srcProvince,
		SrcCity:      srcCity,
		SrcCounty:    srcCounty,
		DestProvince: destProvince,
		DestCity:     destCity,
		DestCounty:   destCounty,
		Price:        rq.Price,
		ShipmentTime: rq.ShipmentTime,
		VehicleLoad:  rq.Load,
		State:        0,
	})

	if err == nil {
		pubId.Encode(ID_Shard, ID_Ver, ID_Carrier_Pub_Category, id)
	} else {
		util.GetLogger().Error("[model - CarrierPub] - error: %s", err.Error())
		err = errors.New(errors.MSG_Logi_Carrier_Pub_AddOrUpdate_Error)
	}

	return
}

func (L Logistics) CancelCarrierPub(mbrId, carrierPubId ID) (err error) {
	var repo data.LogisticsRepo
	var mId, pubId int64
	if _, _, _, mId, err = mbrId.Decode(); err != nil {
		err = errors.New(errors.MSG_Mbr_Invalid)
		return
	}

	if _, _, _, pubId, err = carrierPubId.Decode(); err != nil {
		err = errors.New(errors.MSG_Logi_Invalid_Pub_Id)
		return
	}

	if err = repo.CancelCarrierPub(int(mId), int(pubId)); err != nil {
		util.GetLogger().Error("[model-CancelCarrierPub] - error:%s", err.Error())
	}
	return
}

func (l Logistics) GetCarrierPub(mbrId ID) (rs CarrierPubRS, err error) {
	var pub data.CarrierPubDto
	var repo data.LogisticsRepo
	_, _, _, id, err := mbrId.Decode()
	if err != nil {
		err = errors.New(errors.MSG_Mbr_Invalid)
	} else {
		if pub, err = repo.GetCarrierPub(int(id)); err == nil {
			var pubId ID
			pubId.Encode(ID_Shard, ID_Ver, ID_Carrier_Pub_Category, int64(pub.Id))
			rs.Id = pubId
			rs.State = pub.State
			rs.Price = pub.Price
			rs.Load = pub.VehicleLoad
			rs.ShipmentTime = pub.ShipmentTime
			rs.StartArea = l.chooseArea(pub.SrcProvince, pub.SrcCity, pub.SrcCounty)
			rs.EndArea = l.chooseArea(pub.DestProvince, pub.DestCity, pub.DestCounty)
		} else {
			util.GetLogger().Error("[model-GetCarrierPub] - error:%s", err.Error())
			err = nil
		}
	}
	return
}

func (l Logistics) QueryCarrierPubList(rq QueryCarrierPubListRQ) (rs CarrierPubListRS, err error) {
	var list []data.CarrierPubListDto
	var repo data.LogisticsRepo
	var rowCount int
	param := l.getQueryCarrierPubListCond(rq)
	if list, rowCount, err = repo.QueryCarrierPubList(param); err == nil {
		pubs := make([]CarrierPubList, len(list))
		for idx, dto := range list {
			var carrierPubId, mbrId ID
			carrierPubId.Encode(ID_Shard, ID_Ver, ID_Carrier_Pub_Category, int64(dto.CarrierPubId))
			mbrId.Encode(ID_Shard, ID_Ver, ID_Member_Category, int64(dto.OwnerId))

			pubs[idx] = CarrierPubList{
				OwnerName:       dto.OwnerName,
				OwnerStars:      dto.OwnerStars,
				OwnerPhone:      dto.OwnerPhone,
				OwnerId:         mbrId,
				CarrierPubId:    carrierPubId,
				VehicleType:     dto.VehicleType,
				VehicleLen:      dto.VehicleLen,
				VehicleLoad:     dto.VehicleLoad,
				VehiclePhotoUrl: dto.VehiclePhotoUrl,
				ShipmentTime:    dto.ShipmentTime,
				Price:           dto.Price,
			}

			pubs[idx].StartArea = l.chooseArea(dto.SrcProvince, dto.SrcCity, dto.SrcCounty)
			pubs[idx].EndArea = l.chooseArea(dto.DestProvince, dto.DestCity, dto.DestCounty)
		}
		rs = CarrierPubListRS{TotalCount: rowCount, List: pubs}
	} else {
		util.GetLogger().Error("[model-QueryCarrierPubList] - error:%s", err.Error())
		err = nil
	}
	return
}

func (l Logistics) GetCarrierPubDetail(pubId ID) (rs CarrierPubDetailRS, err error) {
	var pub data.CarrierPubDetail
	var repo data.LogisticsRepo
	_, _, _, id, err := pubId.Decode()
	if err != nil {
		err = errors.New(errors.MSG_Logi_Invalid_Pub_Id)
	} else {
		var mbrId ID
		if pub, err = repo.GetCarrierPubDetail(int(id)); err == nil {
			mbrId.Encode(ID_Shard, ID_Ver, ID_Member_Category, int64(pub.MemberId))
			rs.Name = pub.Name
			rs.OwnerPhone = pub.OwnerPhone
			rs.OwnerStars = pub.OwnerStars
			rs.CarrierPubId = string(pubId)
			rs.MemberId = string(mbrId)
			rs.VehicleType = pub.VehicleType
			rs.VehicleLen = pub.VehicleLen
			rs.VehicleNo = pub.VehicleNo
			rs.VehicleLoad = pub.VehicleLoad
			rs.Price = pub.Price
			rs.VehicleLoad = pub.VehicleLoad
			rs.ShipmentTime = pub.ShipmentTime
			rs.MemberPhotoUrl = pub.MemberPhotoUrl
			rs.CargoType = ""
			rs.StartArea = l.chooseArea(pub.SrcProvince, pub.SrcCity, pub.SrcCounty)
			rs.EndArea = l.chooseArea(pub.DestProvince, pub.DestCity, pub.DestCounty)
		} else {
			util.GetLogger().Error("[model-GetCarrierPubDetail] - error:%s", err.Error())
			err = nil
		}
	}
	return
}

func (l Logistics) getQueryCarrierPubListCond(rq QueryCarrierPubListRQ) data.QueryCarrierPubListParam {
	var param data.QueryCarrierPubListParam
	if startAreaId, err := strconv.Atoi(rq.StartArea); err == nil {
		param.StartArea = startAreaId
	}
	if endAreaId, err := strconv.Atoi(rq.EndArea); err == nil {
		param.EndArea = endAreaId
	}
	if timeBegin, err := time.Parse("2006-01-02", rq.TimeBegin); err == nil {
		if timeBegin.Before(time.Now().AddDate(0, 0, -3)) {
			timeBegin = time.Now().AddDate(0, 0, -3)
		}

		param.TimeBegin = timeBegin.Format("2006-01-02 00:00:00")
	}
	if timeEnd, err := time.Parse("2006-01-02", rq.TimeEnd); err == nil {
		param.TimeEnd = timeEnd.AddDate(0, 0, 1).Format("2006-01-02 00:00:00")
	}
	if _, err := strconv.Atoi(rq.VehicleType); err == nil {
		param.VehicleType = rq.VehicleType
	}
	if _, err := strconv.Atoi(rq.VehicleLoad); err == nil {
		param.VehicleLoad = rq.VehicleLoad
	}
	if _, err := strconv.Atoi(rq.VehicleLen); err == nil {
		param.VehicleLen = rq.VehicleLen
	}
	if rq.PageNo >= 1 {
		param.PageNo = rq.PageNo
	} else {
		param.PageNo = 1
	}
	if rq.PageSize >= 1 && rq.PageSize <= 20 {
		param.PageSize = rq.PageSize
	} else {
		param.PageSize = 10
	}

	return param
}
